# -*- coding: utf-8 -*-
# !/usr/bin/env python
"""
-------------------------------------------------
   File Name：     metric
   Description :   
   Author :       lth
   date：          2022/1/27
-------------------------------------------------
   Change Activity:
                   2022/1/27 13:34: create this script
-------------------------------------------------
this script is used to calculate the performance of the weight
"""
__author__ = 'lth'

import numpy as np


class Evaluator(object):
    """

    这里是专门为这个表格识别设计的分割度量方法，该类为表格分割专门使用

    """

    def __init__(self, num_class,threshold=0.5):
        self.num_class = num_class + 1
        self.confusion_matrix = np.zeros((self.num_class,) * 2)  # 创建混淆矩阵
        self.threshold=threshold

    def Pixel_Accuracy(self):
        Acc = np.diag(self.confusion_matrix).sum() / self.confusion_matrix.sum()  # 对角线上的是预测对的像素点，统计之后和整个的和去除
        return Acc

    def Mean_Intersection_over_Union(self):
        MIoU = np.diag(self.confusion_matrix) / (
                np.sum(self.confusion_matrix, axis=1) + np.sum(self.confusion_matrix, axis=0) -
                np.diag(self.confusion_matrix)+1e-5)
        MIoU = np.mean(MIoU)
        return MIoU

    def Frequency_Weighted_Intersection_over_Union(self):
        """
        这里计算的是预测得到的各类型像素点所占的比例
        """
        eps = 1e-8
        freq = np.sum(self.confusion_matrix, axis=1) / np.sum(self.confusion_matrix)
        iu = np.diag(self.confusion_matrix) / (
                np.sum(self.confusion_matrix, axis=1) + np.sum(self.confusion_matrix, axis=0) -
                np.diag(self.confusion_matrix) + eps)

        FWIoU = (freq[freq > 0] * iu[freq > 0]).sum()
        return FWIoU

    def kappa(self):
        pe_rows = np.sum(self.confusion_matrix, axis=0)
        pe_cols = np.sum(self.confusion_matrix, axis=1)
        sum_total = sum(pe_cols)
        pe = np.dot(pe_rows, pe_cols) / float(sum_total ** 2)
        # np.trace求矩阵的迹，即对角线的和
        po = np.trace(self.confusion_matrix) / float(sum_total)
        return (po - pe) / (1 - pe)

    def _generate_matrix(self, gt_image, pre_image):
        pre_image = pre_image >= self.threshold
        gt_image = gt_image>= self.threshold
        confusion_matrix = np.zeros((self.num_class,) * 2)
        for i in range(4):
            confusion_matrix[i][i] = np.sum(np.multiply(pre_image[:, i, ...], gt_image[:, i, ...]))
            confusion_matrix[i][-1] = np.sum(pre_image[:, i, ...]) - np.sum(
                np.multiply(pre_image[:, i, ...], gt_image[:, i, ...]))
            confusion_matrix[-1][-1] += np.sum(np.multiply(1 - pre_image[:, i, ...], 1 - gt_image[:, i, ...]))
            confusion_matrix[-1][i] = np.sum(1 - pre_image[:, i, ...]) - np.sum(
                np.multiply(1 - pre_image[:, i, ...], 1 - gt_image[:, i, ...]))

        return confusion_matrix

    def update(self, gt_image, pre_image):
        # assert gt_image.shape == pre_image.shape
        self.confusion_matrix += self._generate_matrix(gt_image, pre_image)

    def reset(self):
        self.confusion_matrix = np.zeros((self.num_class,) * 2)


import time


class Timer(object):
    def __init__(self):
        self.tot_time = 0.
        self.calls = 0
        self.start_time = 0.
        self.diff = 0.
        self.average_time = 0.

    def tic(self):
        # using time.time instead of time.clock because time time.clock
        # does not normalize for multithreading
        self.start_time = time.time()

    def toc(self, average=True):
        self.diff = time.time() - self.start_time
        self.tot_time += self.diff
        self.calls += 1
        self.average_time = self.tot_time / self.calls
        if average:
            return self.average_time
        else:
            return self.diff
